
/* list.h: заголовочный файл с функциями работы со списком */

#ifndef LIST_H
#define LIST_H

#include "preproc.h"
#include "interpreter.h"

int		set_type		(gvars_t*, string, type_t);
int		test_obj_c		(gvars_t*);
void	create_object	(gvars_t*, string, type_t, void*);
obj_t*	find_obj		(gvars_t*, string);
int		del_obj			(gvars_t*, string);
int		clear_list		(gvars_t*);
void    mark_gbg        (gvars_t*, string);
void	show_objects	(gvars_t*);

int set_type(gvars_t* gvars, string name, type_t type)
{
	obj_t* view = find_obj(gvars, name);

	if(!view)
		return ERROR;

	view->type = type;

	#ifdef DEBUG_INTERPRETER
	puts("setted");
	#endif

	return SUCCESS;
}

int test_obj_c(gvars_t* gvars)
{
	if(gvars->obj_count >= MAX_OBJ)
		return ERROR;

	return SUCCESS;
}

void create_object(gvars_t* gvars, string name, type_t type, void* data)
{
	if(!gvars->root_obj)
	{
		#ifdef DEBUG_INTERPRETER
		puts("null obj, creating new");
		#endif

		gvars->root_obj = malloc(sizeof(obj_t));
		gvars->last_obj = gvars->root_obj;

		if(gvars->root_obj)
		{
			gvars->root_obj->name = (string) malloc(strlen(name) * sizeof(char));
			strcpy(gvars->root_obj->name, name);
			gvars->root_obj->type = type;
			gvars->root_obj->data = data;

			gvars->root_obj->next = NULL;

			gvars->obj_count++;

			#ifdef DEBUG_INTERPRETER
			puts("create");
			#endif
			
			gvars->result = SUCCESS;
		}
		else
			gvars->result = ERROR;
	}
	else
	{
		if(!test_obj_c(gvars))
		{
			#ifdef DEBUG_INTERPRETER
			puts("root exist, adding new");
			#endif

			gvars->last_obj->next = malloc(sizeof(obj_t));

			gvars->last_obj = (obj_t*) gvars->last_obj->next;

			if(gvars->last_obj)
			{
				gvars->last_obj->name = (string) malloc(strlen(name) * sizeof(char));
				strcpy(gvars->last_obj->name, name);
				gvars->last_obj->type = type;
				gvars->last_obj->data = data;

				gvars->last_obj->next = NULL;

				gvars->obj_count++;

				#ifdef DEBUG_INTERPRETER
				puts("added & init");
				#endif

				gvars->result = SUCCESS;
			}
			else
				gvars->result = ERROR;
		}
		else
			gvars->result = ERROR;
	}
}

obj_t* find_obj(gvars_t* gvars, string name)
{
	obj_t* view = gvars->root_obj;

	while(view)
	{
		if(view->type != GBG_T)
		{
			if (TEST(name,view->name))
			{
				#ifdef DEBUG_INTERPRETER
				puts("finded");
				#endif

				return view;
			}
		}

		view = (obj_t*) view->next;
	}

	return NULL;
}

int del_obj(gvars_t* gvars, string name)
{
	obj_t	*view = gvars->root_obj,
			*prev = view;

	while(view)
	{
		if(TEST(name, view->name))
		{
			prev->next = view->next;

			a_free(view);

			return SUCCESS;
		}
		else
		{
			prev = view;
			view = (obj_t*) view->next;
		}
	}

	return ERROR;
}

int clear_list(gvars_t* gvars)
{
	obj_t	*view = (obj_t*) gvars->root_obj->next,
			*prev = gvars->root_obj;

	while(view)
	{
		prev = view;
		view = (obj_t*) view->next;
		a_free(prev);
	}

	return SUCCESS;
}

void clear_garbage(gvars_t* gvars)
{
	obj_t 	*view = gvars->root_obj,
			*prev = NULL;
	int		 i;

	for(i = 0; i < gvars->obj_count; ++i)
	{
		if(view->type == GBG_T)
		{
			if(prev)
			{
				prev->next = view->next;
				a_free(view);
			}
			else
			{
				gvars->root_obj = (obj_t*) view->next;
			}
		}
	}
}

void mark_gbg(gvars_t* gvars, string name)
{
	obj_t* view = find_obj(gvars, name);

	if(view)
	{
		view->type = GBG_T;

		#ifdef DEBUG_INTERPRETER
		puts("marked");
		#endif

		gvars->result = SUCCESS;
	}

	gvars->result = ERROR;
}

void show_objects(gvars_t* gvars)
{
	obj_t* view = gvars->root_obj;
	int i;

	for(i = 0; i < gvars->obj_count; ++i)
	{
		switch(view->type)
		{
			case 0:
				printf("Name: %s\nType: object\n",
						view->name);
			break;

			case 1:
				printf("Name: %s\nType: string\nValue: %s\n",
						view->name, view->data);
			break;

			case 2:
				printf("Name: %s\nType: file\n",
						view->name);
			break;

			case 3:
				printf("Name: %s\nType: path\nValue: %s\n",
						view->name, view->data);
			break;

			case 4:
				printf("Name: %s\nType: garbage\n",
						view->name);
			break;

			default:
				break;
		}

		view = view->next;
	}
}


#endif
